package controllers

import (
	"goravel/app/models"
	"goravel/app/scopes"
	"goravel/utils/response"

	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
)

type RolesController struct {
	BaseController
}

func NewRolesController() *RolesController {
	return &RolesController{}
}

// Index GET /roles
func (c *RolesController) Index(ctx http.Context) http.Response {
	var roles []models.Role
	var total int64

	page, perPage := c.GetPaginationParams(ctx)

	query := scopes.Query(ctx)

	if roleName := ctx.Request().Query("role_name"); roleName != "" {
		query = query.Where("role_name", "like", "%"+roleName+"%")
	}

	query = query.OrderBy("id", "desc")

	if err := query.Paginate(page, perPage, &roles, &total); err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	return response.Paginate(ctx, roles, total, page, perPage)
}

// Show GET /roles/{id}
func (c *RolesController) Show(ctx http.Context) http.Response {
	var model models.Role

	if err := scopes.Query(ctx).FindOrFail(&model, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	// 获取角色的权限
	permissions, err := model.GetPermissions()
	if err != nil {
		facades.Log().Errorf("Failed to get role permissions: %v", err)
		permissions = []models.Permission{}
	}

	return response.Success(ctx, http.Json{
		"role":        model,
		"permissions": permissions,
	})
}

// Store POST /roles
func (c *RolesController) Store(ctx http.Context) http.Response {
	validator, err := ctx.Request().Validate(map[string]string{
		"role_name": "required|string",
	})

	if err != nil {
		return response.Fail(ctx, http.StatusBadRequest, "Validation failed: "+err.Error())
	}

	if validator.Fails() {
		return response.Fail(ctx, http.StatusBadRequest, validator.Errors().One())
	}

	var roleExists bool
	if err := scopes.Query(ctx).Model(&models.Role{}).Where("role_name", ctx.Request().Input("role_name")).Exists(&roleExists); err != nil {
		return response.Fail(ctx, http.StatusBadRequest, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	} else if roleExists {
		return response.Fail(ctx, http.StatusBadRequest, "角色名已存在")
	}

	role := models.Role{
		RoleName:    ctx.Request().Input("role_name"),
		Description: ctx.Request().Input("description"),
	}

	if err := scopes.Query(ctx).Create(&role); err != nil {
		facades.Log().Errorf("Failed to create role: %v, request data: %+v", err, ctx.Request().All())
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_create"))
	}

	return response.Success(ctx, http.Json{
		"id":          role.ID,
		"role_name":   role.RoleName,
		"description": role.Description,
	})
}

// Update PUT /roles/{id}
func (c *RolesController) Update(ctx http.Context) http.Response {
	var model models.Role

	if err := scopes.Query(ctx).FindOrFail(&model, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	validator, err := ctx.Request().Validate(map[string]string{
		"role_name": "string",
	})

	if err != nil {
		return response.Fail(ctx, http.StatusBadRequest, "Validation failed: "+err.Error())
	}

	if validator.Fails() {
		return response.Fail(ctx, http.StatusBadRequest, validator.Errors().One())
	}

	if roleName := ctx.Request().Input("role_name"); roleName != "" {
		model.RoleName = roleName
	}

	if description := ctx.Request().Input("description"); description != "" {
		model.Description = description
	}

	if err := scopes.Query(ctx).Save(&model); err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_update"))
	}

	return response.Success(ctx, http.Json{
		"data": model,
	})
}

// Destroy DELETE /roles/{id}
func (c *RolesController) Destroy(ctx http.Context) http.Response {
	var model models.Role

	res, err := scopes.Query(ctx).Model(&model).Where("id", ctx.Request().RouteInt("id")).Delete()
	if err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_delete"))
	}

	if res.RowsAffected == 0 {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.no_deleted"))
	}

	return response.Success(ctx, http.Json{
		"id":            model.ID,
		"rows_affected": res.RowsAffected,
	})
}

// GetRolePermissions GET /roles/{id}/permissions
func (c *RolesController) GetRolePermissions(ctx http.Context) http.Response {
	var role models.Role

	if err := scopes.Query(ctx).FindOrFail(&role, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	permissions, err := role.GetPermissions()
	if err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, "Failed to get role permissions")
	}

	return response.Success(ctx, http.Json{
		"permissions": permissions,
	})
}

// GetRoleUsers GET /roles/{id}/users
func (c *RolesController) GetRoleUsers(ctx http.Context) http.Response {
	var role models.Role

	if err := scopes.Query(ctx).FindOrFail(&role, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	users, err := role.GetUsers()
	if err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, "Failed to get role users")
	}

	return response.Success(ctx, http.Json{
		"users": users,
	})
}
